﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace _05LockExmple01
{
    class Account
    {
        int balance;

        Random r = new Random();

        public Account(int initial)
        {
            balance = initial;
        }

        int Withdraw(int amount)
        {

            if (balance < 0)
            {
                throw new Exception("Balance为负数！");
            }
            return UseLock(amount);
            //return UseMonitor(amount);
            //return UseInterlocked(amount);

        }
        int UseLock(int amount)
        {
            lock (this)
            {
                if (balance >= amount)
                {
                    Thread.Sleep(5);
                    balance = balance - amount;
                    return amount;
                }
                else
                {
                    return 0; // transaction rejected
                }
            }
        }
        int UseMonitor(int amount)
        {
            try
            {
                //I.不限时间
                //Monitor.Enter(this);  

                //II.在指定时间获得排他锁
                if (Monitor.TryEnter(this, TimeSpan.FromSeconds(30)))
                //在30秒内获取对象排他锁.
                {
                    if (balance >= amount)
                    {
                        Thread.Sleep(5);
                        balance = balance - amount;
                        return amount;
                    }
                    else
                    {
                        return 0; // transaction rejected
                    }
                }
            }
            catch
            {
                //发生异常后自定义错误处理代码
            }
            finally
            {
                Monitor.Exit(this);  //不管是正常还是发生错误，都得释放对象

            }
            return 0;
        }

        int UseInterlocked(int amount)
        {
            if (balance >= amount)
            {
                int nOld = balance - amount;
                Thread.Sleep(5);
                balance = balance - amount;

                Interlocked.CompareExchange(ref balance, nOld, nOld);

                return amount;
            }
            else
            {
                return 0; // transaction rejected
            }
        }
        public void DoTransactions()
        {
            for (int i = 0; i < 100; i++)
            {
                Withdraw(r.Next(-50, 100));
            }
        }
    }
    class Program
    {
        static Thread[] threads = new Thread[10];
        static void Main(string[] args)
        {
            Account acc = new Account(0);
            for (int i = 0; i < 10; i++)
            {
                Thread t = new Thread(new ThreadStart(acc.DoTransactions));
                threads[i] = t;
            }
            for (int i = 0; i < 10; i++)
            {
                threads[i].Start();
            }
            Console.WriteLine("线程已经启动！！");
            Console.ReadLine();
        }
    }
}
